﻿#pragma once

#include "df.h"
#include "Reflection.h"


namespace df
{

	namespace jsonSymbol
	{
		const TCHAR charSymbol = tt_('"');
		const TCHAR keySymbol = tt_('"');
		const TCHAR objSymbol1 = tt_('{');
		const TCHAR objSymbol2 = tt_('}');

		const TCHAR assignSymbol = tt_(':');

		const TCHAR escapeSymbol = tt_('\\');

		const TCHAR arraySymbol1 = tt_('[');
		const TCHAR arraySymbol2 = tt_(']');
		const TCHAR arraySplitSymbol = tt_(',');
		const int stackSize = 128;
	}

	class json
	{
	public:
	


		//*******************************************
		// Summary : 将s中的charSymbol号加转义escapeSymbol
		// Parameter - const df::CC & s : 
		// Parameter - String & val_ : 储存结果
		//*******************************************
		inline static void EscapeStr(const df::CC & s, String & val_)
		{
			val_ += jsonSymbol::charSymbol;

			for (auto c : s)
			{
				//转义
				if (c == jsonSymbol::charSymbol || c == jsonSymbol::escapeSymbol)
					val_ += jsonSymbol::escapeSymbol;
				val_ += c;
			}
			val_ += jsonSymbol::charSymbol;
		}

		//*******************************************
		// Summary : 将obj转为json字串
		// Parameter - OT & obj : 
		// Returns - void : 
		//*******************************************
		template<class OT>
		inline static void ObjToJson(OT & obj, String & jsonStr)
		{
			parseObj(obj, jsonStr);
		}

	private:
		inline static const TCHAR * tabChar()
		{
			return tt_("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t");
		}

		inline static void addKey(const df::CC & name, String & jsonStr)
		{
			jsonStr << jsonSymbol::keySymbol << name << jsonSymbol::keySymbol << jsonSymbol::assignSymbol;
		}

		//************************************
		// Method:    匹配数字类型
		// Returns:   void
		// Parameter: const df::CC name 对象成员名
		// Parameter: OT obj 对象引用
		// Parameter: String & jsonStr 结果
		//************************************
		template<class OT
			, typename std::enable_if<std::is_integral<OT>::value || std::is_floating_point<OT>::value>::type * = nullptr>
			inline 	static void parseObj(OT obj, String & jsonStr)
		{
			jsonStr << obj;
		}

		//bool类型
		inline static void parseObj(bool obj, String & jsonStr)
		{
			jsonStr << (obj ? tcc_("true") : tcc_("false"));
		}

		//匹配可反射对象
		template<class OT
			, typename std::enable_if<Reflection<OT>::Support>::type * = nullptr>
			static void parseObj(OT & obj, String & jsonStr)
		{
			jsonStr << jsonSymbol::objSymbol1;

			//遍历对象成员
			EnumMetaMember<OT>::Start(ObjEnum<OT>({ obj, jsonStr}));

			//删除末尾多余的,号
			if (OT::Meta_Data::member_Size > 0)
				jsonStr.pop_back();

			jsonStr << jsonSymbol::objSymbol2;
		}



		//匹配数组
		template<class OT>
		inline static void parseList(OT & obj, String & jsonStr)
		{
			jsonStr << jsonSymbol::arraySymbol1;

			for (auto & v : obj)
			{
				parseObj(v, jsonStr);
				jsonStr << jsonSymbol::arraySplitSymbol;
			}

			if (obj.size() > 0)
				jsonStr.pop_back();

			jsonStr << jsonSymbol::arraySymbol2;
		}

		//匹配vector
		template<class OT>
		inline static void parseObj(std::vector<OT> & obj, String & jsonStr)
		{
			parseList(obj, jsonStr);
		}

		//匹配list
		template<class OT>
		inline static void parseObj(std::list<OT> & obj, String & jsonStr)
		{
			parseList(obj, jsonStr);
		}

		//匹配queue
		template<class OT>
		inline static void parseObj(std::queue<OT> & obj, String & jsonStr)
		{
			parseList(obj, jsonStr);
		}

		//匹配map
		template<class TMap>
		inline static void parseMap(TMap & obj, String & jsonStr)
		{
			jsonStr << jsonSymbol::objSymbol1;

			for (auto & v : obj)
			{
				jsonStr << jsonSymbol::keySymbol << v.first;
				jsonStr << jsonSymbol::keySymbol << jsonSymbol::assignSymbol;
				parseObj(v.second, jsonStr);
				jsonStr << jsonSymbol::arraySplitSymbol;
			}

			if (obj.size() > 0)
				jsonStr.pop_back();

			jsonStr << jsonSymbol::objSymbol2;
		}

		//匹配map
		template<class TKey,class TVal>
		inline static void parseObj(std::map<TKey, TVal> & obj, String & jsonStr)
		{
			parseMap(obj, jsonStr);
		}

		//匹配map
		template<class TKey, class TVal>
		inline static void parseObj(std::unordered_map<TKey, TVal> & obj, String & jsonStr)
		{
			parseMap(obj, jsonStr);
		}

		//匹配字串类型,需转义
		inline static void parseObj(String & obj, String & jsonStr)
		{
			EscapeStr(obj, jsonStr);
		}

		//匹配字串类型
		inline static void parseObj(const CC & obj, String & jsonStr)
		{
			EscapeStr(obj, jsonStr);
		}

		//其他类型,不支持
		template<class OT
			, typename std::enable_if<
			!std::is_integral<OT>::value && !std::is_floating_point<OT>::value && !Reflection<OT>::Support
		>::type * = nullptr>
			static void parseObj(const df::CC &, OT &, String &)
		{
			static_assert(sizeof(OT) != sizeof(OT), "object can not convert to json");
		}


		//用于遍历对象成员
		template<class T, int TabSize_ = 0>
		struct ObjEnum
		{
			//待遍历的对象
			T & obj_;
			//生成结果字串
			df::String & conf_;


			template<int I>
			inline void operator()()
			{
				//成员类型
				typedef typename T::DF_TEMPLATE Get_Member_Type<I>::type ValT;
				//成员名
				const CC & key = obj_.DF_TEMPLATE Get_Member_Name<I>();
				//成员值
				auto & val = obj_.DF_TEMPLATE Get_Member<I>();

				//键
				addKey(key, conf_);

				//值
				parseObj(val, conf_);

				//成员分隔符
				conf_ << jsonSymbol::arraySplitSymbol;

			}
		};

	private:

		DF_DISABLE_COPY_ASSIGN(json);
	};



};
